package com.example.common.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.junit.Test;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
@Component
@Configuration
//@RefreshScope  //配置信息热更新（@Value），类似下面方式
@ConfigurationProperties(prefix = "jwt")
public class JwtUtil {

    //    private static final String SECRET_KEY = "mySecretKey";  // 密钥
    // 使用 Keys.secretKeyFor 方法生成适用于 HS256 算法的密钥
    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    private static final String user = "yyz";


    // 生成 JWT，包含自定义数据,生成Token
    public static String generateToken(String userId, long expire, String role) {
        //创建jwt构造器
        JwtBuilder builder = Jwts.builder();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        // 设置过期时间（例如 1 小时）
        long expMillis = nowMillis + expire;  // 1小时(1000*60*60)
        Date exp = new Date(expMillis);
        return builder
                //头部
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                //载荷
                .setId(UUID.randomUUID().toString())//唯一标志
                .setIssuer(user)//签发现人
                .setIssuedAt(now)  // 签发时间
//                .setSubject("jwtDemo")//自定义主题(主题部分，通常是用户名或ID)
                .setSubject(userId)
                .setExpiration(exp)  // 过期时间
                .claim("role", role)
                //签名
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();  // 返回 JWT 字符串
    }


    // 生成 JWT，包含自定义数据
    public static String generateToken(long expire, Map map) {
        //创建jwt构造器
        JwtBuilder builder = Jwts.builder();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        // 设置过期时间（例如 1 小时）
        long expMillis = nowMillis + expire;  // 1小时(1000*60*60)
        Date exp = new Date(expMillis);
        return builder
                //头部
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                //载荷
                .setId(UUID.randomUUID().toString())//唯一标志
                .setIssuer("laoli")//签发现人
                .setIssuedAt(now)  // 签发时间
                .setSubject("jwtDemo")//自定义主题(主题部分，通常是用户名或ID)
                .setExpiration(exp)  // 过期时间
                .addClaims(map)  // 添加自定义的 claims
                //签名
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();  // 返回 JWT 字符串
    }


    // 生成 JWT，包含自定义数据
    public static String parseJwt(String username, String role, String[] permissions) {
        // 当前时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        // 设置过期时间（例如 1 小时）
        long expMillis = nowMillis + 3600000;  // 1小时
        Date exp = new Date(expMillis);

        // 自定义数据
        Map<String, Object> claims = new HashMap<>();
        claims.put("role", role);  // 角色
        claims.put("permissions", permissions);  // 权限列表

        // 生成 JWT Token，添加自定义数据到 claims 中
        return Jwts.builder()
                .setSubject(username)  // 主题部分，通常是用户名或ID
                .setIssuedAt(now)  // 签发时间
                .setExpiration(exp)  // 过期时间
                .addClaims(claims)  // 添加自定义的 claims
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)  // 使用密钥签名
                .compact();  // 返回 JWT 字符串
    }

    //解析token,获取主体部分
    public static Claims parseToken(String token) {
        try {
            return Jwts.parser()  // 创建 JWT 解析器
                    .setSigningKey(SECRET_KEY)  // 设置签名密钥
                    .build()
                    .parseSignedClaims(token)  // 解析 Token
                    .getPayload();  // 提取 Claims 部分
        } catch (ExpiredJwtException e) {
            throw new RuntimeException("Token 已过期", e);  // 捕获 Token 过期异常
        } catch (JwtException e) {
            throw new RuntimeException("无效的 JWT Token", e);  // 捕获其他 JWT 异常
        }
    }

    //    判断是否过期
    public static boolean validateToken(String token) {
        try {
            Claims claims = Jwts.parser()  // 创建 JWT 解析器
                    .setSigningKey(SECRET_KEY)  // 设置签名密钥
                    .build()
                    .parseSignedClaims(token)  // 解析 Token
                    .getPayload();  // 提取 Claims 部分
// 获取 Token 中的过期时间
            Date expiration = claims.getExpiration();

            // 判断 Token 是否过期
            if (expiration.before(new Date())) {
                System.out.println("config-------------------------------Token已经过期!!");
                // Token 已过期
                return false;
            }
            // 如果没有异常，说明 Token 是有效的
            return true;
        } catch (ExpiredJwtException e) {
            // 捕获 Token 过期异常
            System.out.println("令牌已过期: " + e.getMessage());
            return false;
        } catch (Exception e) {
            // 捕获其他解析或验证错误
            System.out.println("令牌验证失败: " + e.getMessage());
            return false;
        }
    }


    @Test
    public void JwtTest() {
        // 生成包含自定义数据的 JWT
        String jwt = generateToken("123456", Long.MAX_VALUE, "admin");
        System.out.println("Key:" + SECRET_KEY);
        System.out.println("Generated JWT: " + jwt);

        // 解析 JWT
        try {
            Claims claims = parseToken(jwt);
            System.out.println("主题: " + claims.getSubject());  // 获取用户名
            System.out.println("Role: " + claims.get("role"));  // 获取角色
//            System.out.println("Permissions: " + claims.get("permissions"));  // 获取权限
            System.out.println("过期时间: " + claims.getExpiration());  // 获取过期时间
        } catch (Exception e) {
            System.out.println("Invalid JWT");
        }
    }

}
